using System;
using System.Text;
using System.Threading.Tasks;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Bluetooth.Advertisement;
using Windows.Storage.Streams;

namespace btserver
{
    public partial class Form1 : Form
    {
        private GattServiceProvider? _serviceProvider;
        private GattLocalCharacteristic? _writeCharacteristic;
        private GattLocalCharacteristic? _notifyCharacteristic;
        private BluetoothLEAdvertisementPublisher? _publisher;

        private readonly Guid _serviceUuid = new Guid("0000ffff-0000-1000-8000-00805f9b34fb");
        private readonly Guid _writeUuid = new Guid("0000ff01-0000-1000-8000-00805f9b34fb");
        private readonly Guid _notifyUuid = new Guid("0000ff02-0000-1000-8000-00805f9b34fb");

        public Form1()
        {
            InitializeComponent();
            this.Load += Form1_Load;
        }

        private void Form1_Load(object? sender, EventArgs e)
        {
            lblStatus.Text = "未启动";
            AppendLog("应用已启动。点击“启动外设”开始广播并被动接受连接。");
        }

        private async void btnStart_Click(object? sender, EventArgs e)
        {
            btnStart.Enabled = false;
            await InitGattAsync();
            btnStart.Enabled = true;
        }

        private void btnStop_Click(object? sender, EventArgs e)
        {
            StopGatt();
        }

        private async void btnSend_Click(object? sender, EventArgs e)
        {
            var text = txtNotify.Text ?? string.Empty;
            await SendNotifyAsync(text);
        }

        private async Task InitGattAsync()
        {
            try
            {
                var result = await GattServiceProvider.CreateAsync(_serviceUuid);
                if (result.Error != BluetoothError.Success)
                {
                    AppendLog($"创建服务失败: {result.Error}");
                    return;
                }

                _serviceProvider = result.ServiceProvider;

                // 写入特征 FF01
                var writeParams = new GattLocalCharacteristicParameters
                {
                    CharacteristicProperties = GattCharacteristicProperties.Write | GattCharacteristicProperties.WriteWithoutResponse,
                    WriteProtectionLevel = GattProtectionLevel.Plain,
                    UserDescription = "FF01 Write"
                };
                var writeCharResult = await _serviceProvider.Service.CreateCharacteristicAsync(_writeUuid, writeParams);
                if (writeCharResult.Error != BluetoothError.Success)
                {
                    AppendLog($"创建写入特征失败: {writeCharResult.Error}");
                    return;
                }
                _writeCharacteristic = writeCharResult.Characteristic;
                _writeCharacteristic.WriteRequested += WriteCharacteristic_WriteRequested;

                // 通知特征 FF02
                var notifyParams = new GattLocalCharacteristicParameters
                {
                    CharacteristicProperties = GattCharacteristicProperties.Notify,
                    ReadProtectionLevel = GattProtectionLevel.Plain,
                    UserDescription = "FF02 Notify"
                };
                var notifyCharResult = await _serviceProvider.Service.CreateCharacteristicAsync(_notifyUuid, notifyParams);
                if (notifyCharResult.Error != BluetoothError.Success)
                {
                    AppendLog($"创建通知特征失败: {notifyCharResult.Error}");
                    return;
                }
                _notifyCharacteristic = notifyCharResult.Characteristic;
                _notifyCharacteristic.SubscribedClientsChanged += NotifyCharacteristic_SubscribedClientsChanged;

                // 启动 GATT 广播（可连接、可发现）
                var advParams = new GattServiceProviderAdvertisingParameters
                {
                    IsConnectable = true,
                    IsDiscoverable = true
                };
                _serviceProvider.StartAdvertising(advParams);
                lblStatus.Text = "已启动 (GATT)";
                AppendLog("GattServiceProvider 已启动广告：可连接、可发现。");

                // 额外发布包含设备名和服务UUID的LE广播（提高手机端发现率）
                try
                {
                    _publisher = new BluetoothLEAdvertisementPublisher();
                    _publisher.Advertisement.LocalName = "PC-GATT";
                    _publisher.Advertisement.ServiceUuids.Add(_serviceUuid);
                    _publisher.StatusChanged += Publisher_StatusChanged;
                    _publisher.Start();
                    AppendLog("AdvertisementPublisher 已启动，包含 LocalName 与 ServiceUUID。");
                }
                catch (Exception ex)
                {
                    AppendLog($"启动额外广播失败: {ex.Message}");
                }
            }
            catch (Exception ex)
            {
                AppendLog($"初始化失败: {ex.Message}");
            }
        }

        private void StopGatt()
        {
            try
            {
                _publisher?.Stop();
                _publisher = null;
                _serviceProvider?.StopAdvertising();
                _serviceProvider = null;
                _writeCharacteristic = null;
                _notifyCharacteristic = null;
                lblStatus.Text = "未启动";
                AppendLog("已停止外设与广播。");
            }
            catch (Exception ex)
            {
                AppendLog($"停止失败: {ex.Message}");
            }
        }

        private async Task SendNotifyAsync(string text)
        {
            if (_notifyCharacteristic == null)
            {
                AppendLog("通知特征未初始化。");
                return;
            }

            var clients = _notifyCharacteristic.SubscribedClients;
            if (clients == null || clients.Count == 0)
            {
                AppendLog("暂无订阅客户端，跳过发送。");
                return;
            }

            var writer = new DataWriter();
            var bytes = Encoding.UTF8.GetBytes(text);
            writer.WriteBytes(bytes);
            var buffer = writer.DetachBuffer();

            try
            {
                var results = await _notifyCharacteristic.NotifyValueAsync(buffer);
                AppendLog($"已向 {results.Count} 客户端发送通知: {text}");
            }
            catch (Exception ex)
            {
                AppendLog($"发送通知失败: {ex.Message}");
            }
        }

        private async void WriteCharacteristic_WriteRequested(GattLocalCharacteristic sender, GattWriteRequestedEventArgs args)
        {
            var deferral = args.GetDeferral();
            try
            {
                var request = await args.GetRequestAsync();
                var reader = DataReader.FromBuffer(request.Value);
                var bytes = new byte[reader.UnconsumedBufferLength];
                reader.ReadBytes(bytes);
                var text = Encoding.UTF8.GetString(bytes);
                AppendLog($"收到写入: {text}");

                // 如果客户端使用 WriteWithResponse，返回响应
                if (request.Option == GattWriteOption.WriteWithResponse)
                {
                    request.Respond();
                }

                // 回声通知（便于手机端验证订阅效果）
                if (!string.IsNullOrEmpty(text))
                {
                    await SendNotifyAsync($"Echo: {text}");
                }
            }
            catch (Exception ex)
            {
                AppendLog($"处理写入失败: {ex.Message}");
            }
            finally
            {
                deferral.Complete();
            }
        }

        private void NotifyCharacteristic_SubscribedClientsChanged(GattLocalCharacteristic sender, object args)
        {
            try
            {
                var count = sender.SubscribedClients?.Count ?? 0;
                AppendLog($"订阅客户端变更，当前数量: {count}");
            }
            catch (Exception ex)
            {
                AppendLog($"订阅事件错误: {ex.Message}");
            }
        }

        private void Publisher_StatusChanged(BluetoothLEAdvertisementPublisher sender, BluetoothLEAdvertisementPublisherStatusChangedEventArgs args)
        {
            AppendLog($"Advertisement 状态: {args.Status}, 错误: {args.Error}");
        }

        private void AppendLog(string message)
        {
            if (txtLog.InvokeRequired)
            {
                txtLog.BeginInvoke(new Action(() => AppendLog(message)));
                return;
            }
            var line = $"[{DateTime.Now:HH:mm:ss}] {message}";
            txtLog.AppendText(line + Environment.NewLine);
        }
    }
}
